package repository

import (
	"bytes"
	"context"
	"encoding/json"
	"gitee.com/cristiane/micro-mall-search/model/elasticsearch"
	"gitee.com/cristiane/micro-mall-search/pkg/code"
	"gitee.com/cristiane/micro-mall-search/vars"
	"gitee.com/kelvins-io/kelvins"
)

func Search(ctx context.Context, index, searchFiled, keyword string) (result elasticsearch.SearchHits, retCode int) {
	retCode = code.Success
	rsp := elasticsearch.SearchResponse{}
	es := vars.ElasticsearchClient
	var buf bytes.Buffer
	query := map[string]interface{}{
		"query": map[string]interface{}{
			"match": map[string]interface{}{
				searchFiled: keyword,
			},
		},
	}
	if err := json.NewEncoder(&buf).Encode(query); err != nil {
		kelvins.ErrLogger.Errorf(ctx, "Search Encode err: %v, query: %v", err, query)
		retCode = code.ErrESSearch
		return
	}
	res, err := es.Search(
		es.Search.WithContext(ctx),
		es.Search.WithIndex(index),
		es.Search.WithBody(&buf),
		es.Search.WithTrackTotalHits(true),
		es.Search.WithPretty(), // 可以使打印体美化
	)
	if err != nil {
		kelvins.ErrLogger.Errorf(ctx, "Search getting response err: %v, query: %v", err, query)
		retCode = code.ErrESSearch
		return
	}
	defer res.Body.Close()
	if res.IsError() {
		var e map[string]interface{}
		if err := json.NewDecoder(res.Body).Decode(&e); err != nil {
			kelvins.ErrLogger.Errorf(ctx, "Search parsing response err: %v, body: %v", err, res.Body)
		} else {
			kelvins.ErrLogger.Errorf(ctx, "Search [%s] %s: %s",
				res.Status(),
				e["error"].(map[string]interface{})["type"],
				e["error"].(map[string]interface{})["reason"],
			)
		}
		retCode = code.ErrESSearch
		return
	}
	if res.StatusCode != 200 {
		retCode = code.ErrESSearch
		return
	}
	if err := json.NewDecoder(res.Body).Decode(&rsp); err != nil {
		kelvins.ErrLogger.Errorf(ctx, "Search Error parsing the response body: %s", err)
		retCode = code.ErrESSearch
		return
	}
	result = rsp.Hits
	return
}
